package org.example.lanchain.config;

import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.store.embedding.EmbeddingStore;
import org.example.lanchain.store.MongoChatMemoryStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.List;

/**
 * 千问聊天记忆配置类
 * 用于配置聊天记忆、向量存储和内容检索等组件
 */
@Configuration  // 标记这是一个 Spring 配置类，用于定义 Bean
public class QwMemoryChat {

    /**
     * 注入 MongoDB 聊天记忆存储实现
     * 用于持久化存储聊天记录
     */
    @Autowired
    MongoChatMemoryStore mongoChatMemoryStore;

    /**
     * 注入文本嵌入模型
     * 用于将文本转换为向量表示
     */
    @Autowired
    private EmbeddingModel embeddingModel;

    /**
     * 注入向量存储
     * 用于存储和检索文本向量
     */
    @Autowired
    private EmbeddingStore embeddingStore;

    /**
     * 定义基础聊天记忆 Bean
     * 使用消息窗口方式，最多保存 10 条消息
     * 
     * @return 返回配置好的聊天记忆实例
     */
    @Bean
    public ChatMemory qwChatMemory() {
        return MessageWindowChatMemory.withMaxMessages(10);
    }

    /**
     * 定义聊天记忆提供者 Bean
     * 为每个会话创建独立的聊天记忆，使用 MongoDB 存储
     * 
     * @return 返回一个函数，该函数接收 memoryId 并返回对应的聊天记忆实例
     */
    @Bean
    public ChatMemoryProvider chatMemoryProvider() {
        return memoryId -> MessageWindowChatMemory.builder()
                .id(memoryId)                    // 设置会话 ID
                .maxMessages(20)                 // 设置每个会话最多保存 20 条消息
                .chatMemoryStore(mongoChatMemoryStore)  // 使用 MongoDB 存储聊天记录
                .build();
    }

    /**
     * 注释掉的内容检索器配置
     * 使用本地文件系统加载文档并存储在内存中
     * 目前已不使用，改用 Pinecone 向量数据库
     */
    // @Bean
    // ContentRetriever contentRetrieverXiaozhi() {
    //     // 从文件系统加载知识库文档
    //     Document document1 = FileSystemDocumentLoader.loadDocument("D:\\BaiduNetdiskDownload\\knowledge\\knowledge\\医院信息.md");
    //     Document document2 = FileSystemDocumentLoader.loadDocument("D:\\BaiduNetdiskDownload\\knowledge\\knowledge\\科室信息.md");
    //     Document document3 = FileSystemDocumentLoader.loadDocument("D:\\BaiduNetdiskDownload\\knowledge\\knowledge\\神经内科.md");
    //     List<Document> documents = Arrays.asList(document1, document2, document3);
    //
    //     // 创建内存向量存储
    //     InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
    //     // 将文档分割并转换为向量，存储到内存中
    //     EmbeddingStoreIngestor.ingest(documents, embeddingStore);
    //     // 创建基于内存向量存储的内容检索器
    //     return EmbeddingStoreContentRetriever.from(embeddingStore);
    // }

    /**
     * 定义基于 Pinecone 的内容检索器 Bean
     * 使用 Pinecone 向量数据库进行相似度搜索
     * 
     * @return 返回配置好的内容检索器实例
     */
    @Bean
    ContentRetriever contentRetrieverDianxiaoerPinecone() {
        return EmbeddingStoreContentRetriever
                .builder()
                .embeddingModel(embeddingModel)    // 设置用于生成向量的模型
                .embeddingStore(embeddingStore)    // 设置向量存储（Pinecone）
                .maxResults(1)                     // 设置每次最多返回 1 个最相似的结果
                .minScore(0.8)                     // 设置最小相似度阈值为 0.8
                .build();
    }
}
